package org.baojie.raft.node.type;

import org.baojie.raft.store.NodeStore;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public abstract class AbstractRole implements Role {

    private final Name name;
    private final NodeStore store;
    private final ReentrantReadWriteLock mainLock = new ReentrantReadWriteLock();
    private final Lock writeLock = mainLock.writeLock();
    private final Lock readLock = mainLock.readLock();
    private volatile int term;

    public AbstractRole(Name name, NodeStore store, int term) {
        this.name = name;
        this.store = store;
        this.writeLock.lock();
        try {
            this.term = term;
        } finally {
            this.writeLock.unlock();
        }
    }

    @Override
    public Name type() {
        return name;
    }

    @Override
    public NodeStore store() {
        return store;
    }

    @Override
    public int getTerm() {
        final Lock read = readLock;
        read.lock();
        try {
            return term;
        } finally {
            read.unlock();
        }
    }

    @Override
    public void setTerm(int term) {
        if (term < 0) {
            return;
        }
        final Lock write = writeLock;
        write.lock();
        try {
            this.term = term;
            this.store.setTerm(term);
        } finally {
            write.unlock();
        }
    }

    @Override
    public void addTerm(int adder) {
        if (adder <= 0) {
            return;
        }
        final Lock write = writeLock;
        write.lock();
        try {
            this.term = this.term + adder;
            this.store.setTerm(this.term);
        } finally {
            write.unlock();
        }
    }

    @Override
    public String toString() {
        return "AbstractRole{" +
                "name=" + name +
                ", store=" + store +
                ", term=" + term +
                '}';
    }
}
